package il.ac.bgu.cs.heuristics.utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Stack;

/**
 * 
 * @author Ronen Pinko
 * 
 */
public final class CollectionUtils { // NOPMD (too many methods) utility class

	private final static Iterable<Object>	EMPTY_ITERABLE	= new Iterable<Object>() {

																@Override
																public Iterator<Object> iterator() {
																	return new Iterator<Object>() {

																		@Override
																		public boolean hasNext() {
																			return false;
																		}

																		@Override
																		public Object next() {
																			throw new NoSuchElementException(
																					"emtpy iteration, no members");
																		}

																		@Override
																		public void remove() {
																			/**
																			 * 
																			 * 
																			 * 
																			 * 
																			 * no
																			 * need
																			 * to
																			 * implement
																			 */
																		}
																	};
																}
															};

	public static <E> Iterable<E> toIterable(Iterator<E> it) {
		final List<E> list = newArrayList();
		while (it.hasNext()) {
			list.add(it.next());
		}
		return list;
	}

	public static <T> Set<T> unmodifiableSet(T... elemets) {
		return Collections.unmodifiableSet(new LinkedHashSet<T>(Arrays
				.asList(elemets)));
	}

	public static <T> Set<T> returnAsSet(T... elemets) {
		return new LinkedHashSet<T>(Arrays.asList(elemets));
	}

	private CollectionUtils() {
	} // no instantiation

	public static <T> ArrayList<T> newArrayList() { // NOPMD (use interface)
		return new ArrayList<T>();
	}

	public static <T> ArrayList<T> newArrayList(int initialCapacity) { // NOPMD
		return new ArrayList<T>(initialCapacity);
	}

	public static <T> ArrayList<T> newArrayList(Collection<T> col) { // NOPMD
		return new ArrayList<T>(col);
	}

	public static <T> Set<T> newLinkedHashSet() { // NOPMD
		return new LinkedHashSet<T>();
	}

	public static <T> Set<T> newLinkedHashSet(int initialCapacity) { // NOPMD
		return new LinkedHashSet<T>(initialCapacity);
	}

	public static <T> Set<T> newLinkedHashSet(Collection<T> col) { // NOPMD
		return new LinkedHashSet<T>(col);
	}

	public static <K, V> HashMap<K, V> newHashMap() { // NOPMD
		return new HashMap<K, V>();
	}

	public static <T> Stack<T> newStack() { // NOPMD
		return new Stack<T>();
	}

	public static <T> StackSet<T> newStackSet() { // NOPMD
		return new StackSet<T>();
	}

	/**
	 * Returns a union of the two lists, while maintaining insertion order
	 */
	public static <T> LinkedHashSet<T> orderedUnion(List<T> list1, List<T> list2) { // NOPMD
		final LinkedHashSet<T> unified = new LinkedHashSet<T>();
		unified.addAll(list1);
		unified.addAll(list2);
		return unified;
	}

	// no need to check cast, the static member is Object typed and have no
	// action
	@SuppressWarnings("unchecked")
	public static <T> Iterable<T> emptyIteration() {
		return (Iterable<T>) EMPTY_ITERABLE;
	}
}
